//
//  HorizontalWaterFallLayout.swift
//  GoAbroad
//
//  Created by Pink Snow on 2025/5/30.
//

import UIKit
protocol HorizontalWaterfallLayoutDelegate: AnyObject {
    func collectionView(_ collectionView: UICollectionView, sizeForItemAt indexPath: IndexPath) -> CGSize
    func numberOfRows(in collectionView: UICollectionView) -> Int
    func heightForRow(at row: Int) -> CGFloat
}

class HorizontalWaterFallLayout: UICollectionViewLayout {

    weak var delegate: HorizontalWaterfallLayoutDelegate?

    private var layoutAttributes: [UICollectionViewLayoutAttributes] = []
    private var contentSize: CGSize = .zero
    private var rowXOffsets: [CGFloat] = []

    private let sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    private let interItemSpacing: CGFloat = 8
    private let rowSpacing: CGFloat = 8

    override func prepare() {
        super.prepare()
        guard let collectionView = collectionView,
              let delegate = delegate else { return }

        layoutAttributes.removeAll()
        let numberOfRows = delegate.numberOfRows(in: collectionView)
        let numberOfItems = collectionView.numberOfItems(inSection: 0)

        // 初始化每行横向起点
        rowXOffsets = Array(repeating: sectionInset.left, count: numberOfRows)

        var yOffsets: [CGFloat] = []
        var currentY: CGFloat = sectionInset.top
        for row in 0..<numberOfRows {
            yOffsets.append(currentY)
            let rowHeight = delegate.heightForRow(at: row)
            currentY += rowHeight + rowSpacing
        }

        for item in 0..<numberOfItems {
            let indexPath = IndexPath(item: item, section: 0)
            let originalSize = delegate.collectionView(collectionView, sizeForItemAt: indexPath)

            // 找出当前最短行
            let row = rowXOffsets.enumerated().min(by: { $0.element < $1.element })?.offset ?? 0
            let rowHeight = delegate.heightForRow(at: row)

            // 等比缩放宽度
            let scale = rowHeight / originalSize.height
            let itemWidth = originalSize.width * scale
            let frame = CGRect(x: rowXOffsets[row],
                               y: yOffsets[row],
                               width: itemWidth,
                               height: rowHeight)

            let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attr.frame = frame.integral
            layoutAttributes.append(attr)

            rowXOffsets[row] = frame.maxX + interItemSpacing
        }

        let contentWidth = (rowXOffsets.max() ?? sectionInset.left) + sectionInset.right
        contentSize = CGSize(width: contentWidth, height: currentY - rowSpacing + sectionInset.bottom)
    }

    override var collectionViewContentSize: CGSize {
        return contentSize
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return layoutAttributes.filter { $0.frame.intersects(rect) }
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        return layoutAttributes.first(where: { $0.indexPath == indexPath })
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }
}
